/*
 * Lenovo Group
 * Copyright (c) 2015-2016 All Rights Reserved.
 * 
 * Project Name:itsm-gateway
 * Create Time: 2016年3月18日 下午10:57:34
 */
package com.lenovo.lmrp.server.itsmgateway.adapter.ms;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lenovo.sdc.framework.cache.ACacheClient;
import com.lenovo.sdc.framework.cache.CacheItem;
import com.lenovo.sdc.framework.scheduler.ACommonTask;
import com.lenovo.sdc.framework.scheduler.Schedule;
import com.lenovo.sdc.framework.util.Tuple;

/**
 * Read ticket sync cache, retry invoke remedy interface to update ticket
 * 
 * @author wujin
 * @version v1.0
 */
public class RetrySyncTicketTask extends ACommonTask {

    private static final Logger logger = LoggerFactory.getLogger(RetrySyncTicketTask.class);
    
    private String itsmCode;
    private ACacheClient cacher;
    private LenovoMSAdapter adapter;
    
    private String taskID;
    private Schedule schedule;
    
    public RetrySyncTicketTask(String itsmCode, ACacheClient cacher, LenovoMSAdapter adapter) {
        super();
        this.itsmCode = itsmCode;
        this.cacher = cacher;
        this.adapter = adapter;
        
        this.schedule = new Schedule(300);
        this.taskID = itsmCode + ":retrysyncticket:" + System.nanoTime();
    }
    
    @Override
    public String getID() {
        return taskID;
    }

    @Override
    public Schedule getSchedule() {
        return schedule;
    }

    @Override
    public void execute() throws Exception {
        // copy ticket avoid lock long time when loop to sync data
        CacheItem<Set<String>> ticketList = cacher.get(itsmCode, LenovoMSAdapter.TICKET_LIST_CACHE_KEY);
        if (Objects.isNull(ticketList.getValue()))
            return;
        
        int counter = 0;
        Set<String> copySet = new HashSet<>(ticketList.getValue());
        Set<String> removedSet = new HashSet<String>();
        for (String ticketID : copySet) {
            CacheItem<List<String>> items = cacher.get(itsmCode, ticketID);
            if (Objects.isNull(items) || Objects.isNull(items.getValue())) {
                removedSet.add(ticketID);
                continue;
            }

            for (Iterator<String> it = items.getValue().iterator(); it.hasNext();) {
                try {
                    String item = it.next();
                    logger.info("sync ticket command:\n {}", item);
                    Tuple.Pair<Boolean, String> result = adapter.updateTicket(item);
                    
                    // if update successed, remote it from cache queue
                    if (result.getOne()) {
                        it.remove();
                        counter ++;
                    }
                }
                catch (Exception exp) {
                    items.setTTL(-1);
                    cacher.put(items);
                    logger.warn("retry sync ticket {}, but meet error broken:{}" , counter, exp.getMessage());
                    return;
                }
            }
            
            // remote synced ticket data from cache
            if (items.getValue().isEmpty()) {
                cacher.remove(itsmCode, ticketID);
                removedSet.add(ticketID);
            }
            else {
                items.setTTL(-1);
                cacher.put(items);
            }
        }
        
        // clean synced ticket from list
        ticketList = cacher.get(LenovoMSAdapter.TICKET_LIST_CACHE_KEY);
        ticketList.getValue().removeAll(removedSet);
        cacher.put(ticketList);
        
        copySet.clear();
        removedSet.clear();
        
        logger.info("retry sync ticket {}", counter);
    }
}
